<template>
	<view>
		<view class="submit-order-price-list">
			<view
				class="price-item"
				:class="{
					checked: item.salable && !item.sold_out && checkedDate === item.date,
					disabled: !item.salable || item.sold_out,
				}"
				v-for="(item, index) in filterPrices"
				:key="index"
				@click="handlePriceClick(item)"
			>
				<view class="week">{{ formatDateToWeek(item.date) }}</view>
				<view class="date">{{ !item.salable || item.sold_out ? "不可订" : dataToDate(item.date, 4) }}</view>
				<image
					:src="`${imgBaseUrl}price-check-icon.png`"
					class="price-check-icon"
					v-if="item.salable && !item.sold_out && checkedDate === item.date"
				/>
			</view>
			<view class="choose-date" @click="showMoreDate">
				<text class="text">选择日期</text>
				<image class="img" :src="`${imgBaseUrl}arrow-right-gray.png`" />
			</view>
		</view>
		<up-calendar
			:show="show"
			@confirm="handleConfirm"
			@close="toggleShow"
			:close-on-click-overlay="false"
			round="12"
			ref="calendar"
			:max-date="end_date"
			:month-num="monthNum"
			:default-date="defaultDate || checkedDate || latest_sale_date"
		></up-calendar>
	</view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from "vue"
import dayjs from "dayjs"
import type { Price } from "@/types/ticket"
import { $getTicketListPrice } from "@/api/ticket"
import { $getCombotktListPrice } from "@/api/combotkt"
import { priceInCent, dataToDate } from "@/mixins/mixins"
import { formatDateToWeek } from "@/utils/tools"

interface SubmitOrderPriceListProps {
	/** ticket: 门票 combotkt: 联票 */
	page_type: "ticket" | "combotkt"
	date: string
	prices: Price[]
	id: string
	latest_sale_date: string
	// 游玩日期为分别选择时的索引
	idx?: number
}

interface CalendarRef {
	setFormatter: (callback: Function) => any
}

const props = defineProps<SubmitOrderPriceListProps>()
const emit = defineEmits(["price-change", "calendar-visible"])

// 从 prices 中过滤而来，最多展示三个
const filterPrices = ref<Price[]>([])
const checkedDate = ref("")
const defaultDate = ref("")
const show = ref(false)
const calendar = ref<CalendarRef | null>(null)
const dateList = ref<Price[]>([])
const imgBaseUrl = inject("imgBaseUrl")

const monthNum = computed(() => (dayjs().date() === 1 ? 3 : 4))
const end_date = computed(() => dayjs(props.latest_sale_date).add(90, "day").format("YYYY-MM-DD"))

const toggleShow = () => {
	show.value = !show.value

	emit("calendar-visible", show.value)
}

const handlePriceClick = (item: Price) => {
	if (item.salable && !item.sold_out) {
		checkedDate.value = item.date
		emit("price-change", { date: item.date, price_in_cent: item.price_in_cent })
	}
}

const getLatestDate = async () => {
	let list: Price[] = []

	const request = {
		ticket: $getTicketListPrice,
		combotkt: $getCombotktListPrice,
	}[props.page_type]

	const data = await request(props.id, props.latest_sale_date, end_date.value)

	if (props.page_type === "ticket") {
		list = (data as { list: Price[] }).list
	}

	if (props.page_type === "combotkt") {
		// 游玩日期为分别选择
		if (typeof props.idx === "number") {
			list = (data as { combo_sale_infos: { prices: Price[] }[] }).combo_sale_infos[props.idx].prices
		} else {
			// 游玩日期为统一选择
			list = (data as { prices: Price[] }).prices
		}
	}

	return list
}

const showMoreDate = async () => {
	const list = await getLatestDate()

	dateList.value = list

	toggleShow()
}

const handleConfirm = (date: Record<string, string>) => {
	if (!date[0]) {
		toggleShow()
		return
	}

	// 先判断选中这天是否可售，因为存在都不可售的情况下，默认选中了当天
	// 如果选中这天不可售，则外面不是选中状态
	const res = dateList.value.find((item) => item.date === date[0])

	if (!res?.salable || res.sold_out) {
		toggleShow()
		return
	}

	const hasExist = filterPrices.value.some((item) => item.date === date[0])

	if (hasExist) {
		const result = filterPrices.value.find((item) => item.date === date[0])

		checkedDate.value = date[0]
		emit("price-change", { date: date[0], price_in_cent: result!.price_in_cent })
	} else {
		const result = dateList.value.find((item) => item.date === date[0])

		if (result) {
			const firstTwoPrices = props.prices.slice(0, 2)
			filterPrices.value = [result, ...firstTwoPrices]
			checkedDate.value = result.date
			emit("price-change", { date: result.date, price_in_cent: result.price_in_cent })
		}
	}

	toggleShow()
}

const formatter = (day: { bottomInfo: string; disabled: boolean; date: Date }) => {
	if (dateList.value.length) {
		if (!dateList.value.some((item) => item.date === dayjs(day.date).format("YYYY-MM-DD"))) {
			day.disabled = true
		} else {
			dateList.value.forEach((item) => {
				if (item.date === dayjs(day.date).format("YYYY-MM-DD")) {
					const disabled = !item.salable || item.sold_out || !item.price_in_cent
					day.disabled = disabled
					day.bottomInfo = disabled ? "不可订" : `￥${priceInCent(+item.price_in_cent)}`
				}
			})
		}
	}

	return day
}

// 寻找是否有可售卖的
const isSellable = (item: Price) => item.salable && !item.sold_out

onMounted(async () => {
	if (calendar.value) {
		calendar.value.setFormatter(formatter)
	}

	if (!props.date) {
		filterPrices.value = props.prices.slice(0, 3)
		return
	}

	if (props.prices.length) {
		let itemObj = { date: "", price_in_cent: "", default_date: "" }

		// 1.先去 props.prices 中查看是否存在 props.date 这天
		const res = props.prices.find((item) => item.date === props.date)

		if (res) {
			// 看 props.date 这天是否可售
			if (isSellable(res)) {
				itemObj.date = res.date
				itemObj.price_in_cent = res.price_in_cent
			} else {
				// 如果 props.date 这天不可售，则往后找可售的那天

				// 先去 props.prices 中查看是否存在可售的
				const sellableItem = props.prices.find(isSellable)

				if (sellableItem) {
					itemObj.default_date = sellableItem.date
				} else {
					// props.prices 中也没有可售的话，那么去找最近 90 天是否存在可售
					const list = await getLatestDate()

					const sellableDate = list.find(isSellable)

					if (sellableDate) {
						itemObj.default_date = sellableDate.date
					}
				}

				itemObj.date = ""
				itemObj.price_in_cent = ""
			}

			const arr = props.prices.slice(0, 3)

			if (arr.some((_item) => _item.date === props.date)) {
				filterPrices.value = arr
			} else {
				filterPrices.value = [res, ...arr.slice(0, 2)]
			}
		} else {
			// 如果 props.prices 中不存在 props.date 这天，那么需要通过接口去查询最近90天中是否存在 props.date 这天
			// 以及要查看它的售卖状态
			const list = await getLatestDate()

			// 查看最近 90 天内是否存在 props.date 这天
			const existData = list.find((item) => item.date === props.date)

			if (!existData) {
				filterPrices.value = props.prices.slice(0, 3)
				uni.showToast({ title: `${props.date}暂不可销售`, icon: "none" })
			} else {
				if (isSellable(existData)) {
					itemObj.date = existData.date
					itemObj.price_in_cent = existData.price_in_cent
					filterPrices.value = [existData, ...props.prices.slice(0, 2)]
				} else {
					const sellableDate = list.find(isSellable)

					if (sellableDate) {
						itemObj.default_date = sellableDate.date
					}

					itemObj.date = ""
					itemObj.price_in_cent = ""
					filterPrices.value = props.prices.slice(0, 3)
					uni.showToast({ title: `${props.date}暂不可销售`, icon: "none" })
				}
			}
		}

		checkedDate.value = itemObj.date
		defaultDate.value = itemObj.default_date
		emit("price-change", { date: itemObj.date, price_in_cent: itemObj.price_in_cent })
	}
})
</script>

<style lang="scss" scoped>
.submit-order-price-list {
	display: flex;
	align-items: center;

	.price-item {
		flex: 1;
		max-width: 148rpx;
		position: relative;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		margin-right: 16rpx;
		padding: 10rpx 0;
		border-radius: 16rpx;
		border: 2rpx solid #e5e6eb;

		.week {
			margin-bottom: 4rpx;
			font-size: 20rpx;
			color: #86909c;
			line-height: 28rpx;
		}

		.date {
			font-size: 24rpx;
			color: #1d2129;
			line-height: 34rpx;
		}

		&.checked {
			border-color: #fee038;
			background: rgba(254, 224, 56, 0.25);

			.week {
				color: #1d2129;
			}

			.price-check-icon {
				position: absolute;
				right: -1rpx;
				bottom: -1rpx;
				width: 24rpx;
				height: 20rpx;
			}
		}

		&.disabled {
			background: #f1f2f5;

			.date {
				color: #86909c;
			}
		}
	}

	.choose-date {
		width: 160rpx;
		display: flex;
		align-items: center;
		padding: 26rpx 20rpx;
		border-radius: 16rpx;
		border: 2rpx solid #e5e6eb;

		.text {
			font-size: 24rpx;
			color: #1d2129;
			line-height: 34rpx;
			margin-right: 6rpx;
		}

		.img {
			width: 12rpx;
			height: 12rpx;
		}
	}
}
</style>
